home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
msysjour
/
vol04
/
02a
/
mdi
/
mdi1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-06
|
20KB
|
658 lines
/*
* MDI1.C - Application Interface
*
* LANGUAGE : Microsoft C5.1
* MODEL : medium
* ENVIRONMENT : Microsoft Windows 2.1 SDK
* STATUS : operational
*
* This module contains all the MDI code to handle the programmatic
* interface. This includes window creation, default message handling,
* and message loop support code. The MDI desktop window and the
* document windows have separate creation and message handling
* routines, while the message loop support is window independant.
*
* Developed by:
* Geoffrey Nicholls
* Kevin P. Welch
*
* (C) Copyright 1988
* Eikon Systems, Inc.
* 989 E. Hillsdale Blvd, Suite 260
* Foster City CA 94404
*
*/
#include <stdio.h>
#include <windows.h>
#include "mdi.h"
/* External variables */
extern int iCurrentPopup; /* What menu is up */
extern int iNextPopup; /* What menu is next */
/**/
/*
* MdiMainCreateWindow( ... ) : HWND;
*
* szClassName Class name of MDI desktop
* szTitleName Caption for MDI desktop
* lStyle Style of MDI desktop
* wLeft Left position of window
* wTop Top position of window
* wWidth Width of window
* wHeight Height of window
* hwndParent Parent of MDI desktop
* hmenuMain Handle to menu
* hInst Current instance handle
* lpCreateParam Pointer to creation parameters
*
* Create the MDI desktop window. The parameters exactly match the
* Windows call CreateWindow(). The MDI code keeps track of desktop
* information in property lists, such as handles to menus,
* accelerators, and bitmaps as well as counts of document windows.
*
*/
HWND MdiMainCreateWindow(
LPSTR szClassName,
LPSTR szTitleName,
DWORD lStyle,
int wLeft,
int wTop,
int wWidth,
int wHeight,
HWND hwndParent,
HMENU hmenuMain,
HANDLE hInst,
LPSTR lpCreateParam )
{
HWND hwndMain; /* Handle of MDI desktop */
hwndMain = CreateWindow( szClassName,
szTitleName,
lStyle,
wLeft, wTop, wWidth, wHeight,
hwndParent,
hmenuMain,
hInst,
lpCreateParam );
/* Success? */
if ( hwndMain )
{
/* Message hook for tracking keyboard interface to menu */
MdiSetMenuKeyHook( hInst );
/* Make sure variables are initialized */
SetProp( hwndMain, PROP_ACTIVE, NULL );
SetProp( hwndMain, PROP_COUNT, 0 );
SetProp( hwndMain, PROP_HIDDEN, 0 );
SetProp( hwndMain, PROP_ZOOM, FALSE );
SetProp( hwndMain, PROP_MAINMENU, GetMenu( hwndMain ) );
SetProp( hwndMain, PROP_WINDOWMENU, LoadMenu(hInst, "MdiMenu") );
SetProp( hwndMain,
PROP_CTRLACCEL,
LoadAccelerators( hInst, "MdiChildAccel" ) );
SetProp( hwndMain,
PROP_SYSMENU,
MdiCreateChildSysBitmap( hwndMain ) );
SetProp( hwndMain, PROP_TITLE, AddAtom( szTitleName ) );
/* Attach window menu to main menu */
MdiWindowMenu( hwndMain, GetMenu( hwndMain ), TRUE);
}
return hwndMain;
}
/**/
/*
* MdiMainDefWindowProc( hwndMain, message, wParam, lParam ) : long;
*
* hwndMain Handle to MDI desktop
* message Current message
* wParam Word parameter to message
* lParam Long parameter to message
*
* Handle the MDI desktop messages. Messages reach here only after
* the application MDI desktop window procedure has processed those
* that it wants. Major occurances that are recognized in this
* function include: parent window activation & deactivation, WINDOW
* menu messages (esp for switching between children), record keeping
* of which menu is currently poped up (if any), and sizing of
* document windows which are maximized.
*
*/
long MdiMainDefWindowProc(
HWND hwndMain,
unsigned message,
WORD wParam,
LONG lParam )
{
FARPROC lpProc; /* Procedure instance for dialogs */
HANDLE hInst; /* Current instance handle */
HWND hwndActive; /* Currently active document window */
HWND hwndChosen; /* Newly chosen document window */
HWND hwndIter; /* Iterating document windows */
LONG lStyle; /* Window style */
RECT rcClient; /* Client area of MDI desktop */
hwndActive = GetProp( hwndMain, PROP_ACTIVE );
switch ( message )
{
case WM_ACTIVATE:
/* MDI child reflects the activation status of the parent */
if ( hwndActive )
{
switch( wParam )
{
case 0:
/* Deactivating */
MdiDeactivateChild( hwndActive );
break;
case 1:
case 2:
/* Activating */
MdiActivateChild( hwndActive, FALSE );
break;
}
}
break;
case WM_COMMAND:
hInst = GetWindowWord( hwndMain, GWW_HINSTANCE );
switch ( wParam )
{
case IDM_UNHIDE:
/* Unhide dialog box */
lpProc = MakeProcInstance( MdiDlgUnhide, hInst );
hwndChosen = DialogBox( hInst, "MdiUnhide", hwndMain, lpProc);
if ( hwndChosen )
{
/* MDI child being unhidden */
MdiUnhideChild( hwndChosen );
}
FreeProcInstance( lpProc );
break;
default:
/* Is this a WINDOW menu message to select an MDI child */
if ( wParam > IDM_FIRSTWIN
&& wParam <= IDM_FIRSTWIN + GetProp( hwndMain, PROP_COUNT))
{
/* Iterate all the children of the mdi parent */
for ( hwndIter = GetTopWindow( hwndMain );
hwndIter != NULL;
hwndIter = GetWindow( hwndIter, GW_HWNDNEXT ) )
{
/* Ignore self & non-mdi children */
if ( hwndIter == hwndActive
|| !GetProp( hwndIter, PROP_ISMDI ) )
{
continue;
}
/* Is this the window? */
if ( wParam == GetProp( hwndIter, PROP_MENUID ) )
{
/* Make a new MDI child the current one */
if ( GetProp( hwndMain, PROP_ZOOM ) )
{
MdiSwitchZoom( hwndIter, hwndActive );
}
MdiActivateChild( hwndIter, FALSE );
break;
}
}
}
else
{
if ( hwndActive )
{
/* MDI child gets all other WM_COMMAND messages */
return SendMessage(hwndActive, message, wParam, lParam);
}
}
break;
}
break;
case WM_DESTROY:
/* Let MDI clean up */
DeleteObject( GetProp( hwndMain, PROP_SYSMENU ) );
DeleteAtom( GetProp( hwndMain, PROP_TITLE ) );
MdiFreeMenuKeyHook( );
break;
case WM_INITMENU:
/* Anything to hide? */
EnableMenuItem( ( HMENU ) wParam,
IDM_HIDE,
hwndActive ? MF_ENABLED : MF_GRAYED );
/* Any hidden windows? Gray UNHIDE appropriately */
EnableMenuItem( ( HMENU ) wParam,
IDM_UNHIDE,
GetProp( hwndMain, PROP_HIDDEN ) ? MF_ENABLED : MF_GRAYED );
/* Maybe the MDI child wants to do something too */
if ( hwndActive )
{
SendMessage( hwndActive, message, wParam, lParam );
}
break;
case WM_INITMENUPOPUP:
/* Keep track of which menu is popped up so that if we hit a left
** or right arrow, we know which the next menu to popup is.
*/
if ( HIWORD( lParam ) )
{
iCurrentPopup = POP_MAINSYS;
}
else
{
iCurrentPopup = LOWORD( lParam );
if ( GetProp( hwndMain, PROP_ZOOM ) )
iCurrentPopup--;
}
if ( hwndActive )
{
/* Let the MDI child do something with this too */
SendMessage( hwndActive, message, wParam, lParam );
}
break;
case WM_MENUCHAR:
if ( wParam == '-' )
{
/* Bring up active MDI child's system menu */
if ( ( LOWORD( lParam ) & MF_POPUP ) == 0 && hwndActive )
{
/* Is the MDI child zoomed? */
if ( GetProp( hwndMain, PROP_ZOOM ) )
{
/* MDI child system menu is on the main menu bar */
return MAKELONG( 0, MC_SELECT );
}
iNextPopup = POP_CHILDSYS;
/* This result will cause no menu to hilite, but because
** iNextPopup is set, the call right after the message
** processing loop will hilite the child system menu
*/
return MAKELONG( 0, MC_ABORT );
}
break;
}
break;
case WM_SETFOCUS:
/* Make the MDI child reflect the focus status of the MDI main */
if ( hwndActive )
{
SetFocus( hwndActive );
}
break;
case WM_SIZE:
if ( wParam != SIZEICONIC )
{
/* Resize MDI child if zoomed */
if ( GetProp( hwndMain, PROP_ZOOM ) )
{
GetClientRect( hwndMain, &rcClient );
lStyle = GetWindowLong( hwndActive, GWL_STYLE );
AdjustWindowRect( &rcClient, lStyle, FALSE );
MoveWindow( hwndActive,
rcClient.left,
rcClient.top,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
TRUE );
}
}
break;
}
return DefWindowProc( hwndMain, message, wParam, lParam );
}
/**/
/*
* MdiChildCreateWindow( ... ) : HWND;
*
* szClassName Class name of document
* szTitleName Caption for document
* lStyle Style of document
* wLeft Left position of window
* wTop Top position of window
* wWidth Width of window
* wHeight Height of window
* hwndMain MDI desktop
* hmenuChild Handle to document menu
* hInst Current instance handle
* lpCreateParam Pointer to creation parameters
*
* Create an MDI document window. The parameters exactly match the
* Windows call CreateWindow() except that the hmenuChild message
* must be a valid menu handle, whereas the CreateWindow() call expects
* a child id. The MDI code keeps track of document information in
* property lists, such as handles to menus and accelerators, as well
* as whether this child of the MDI desktop is an MDI document.
*
*/
HWND MdiChildCreateWindow(
LPSTR szClassName,
LPSTR szTitleName,
DWORD lStyle,
int wLeft,
int wTop,
int wWidth,
int wHeight,
HWND hwndMain,
HMENU hmenuChild,
HANDLE hInst,
LPSTR lpCreateParam )
{
char szTitle[128]; /* Title for document */
char szCompose[128]; /* Used to compose title */
int iCount; /* Child window ID */
int wLeftAct = wLeft; /* Left position of window */
int wTopAct = wTop; /* Top position of window */
int wWidthAct = wWidth; /* Width of window */
int wHeightAct = wHeight; /* Height of window */
HWND hwndActive; /* Currently active document window */
HWND hwndChild; /* Handle of document window */
RECT rcClient; /* Client area of MDI desktop */
/* Calculate size & position */
iCount = GetProp( hwndMain, PROP_COUNT );
if ( wLeftAct == CW_USEDEFAULT )
wLeftAct = 10 + 15 * iCount;
if ( wTopAct == CW_USEDEFAULT )
wTopAct = 10 + 15 * iCount;
if ( wWidthAct == CW_USEDEFAULT )
wWidthAct = 200;
if ( wHeightAct == CW_USEDEFAULT )
wHeightAct = 75;
/* Ensure that it falls within client area */
GetClientRect( hwndMain, &rcClient );
if ( wLeft == CW_USEDEFAULT )
while ( wLeftAct > rcClient.right )
wLeftAct -= rcClient.right;
if ( wTop == CW_USEDEFAULT )
while ( wTopAct > rcClient.bottom )
wTopAct -= rcClient.bottom;
/* Create it */
hwndChild = CreateWindow( szClassName,
szTitleName,
lStyle,
wLeftAct, wTopAct, wWidthAct, wHeightAct,
hwndMain,
( HMENU ) iCount,
hInst,
lpCreateParam );
/* Success? */
if ( hwndChild )
{
/* New child */
SetProp( hwndMain, PROP_COUNT, ++iCount );
/* Keep important info */
SetProp( hwndChild, PROP_CHILDMENU, hmenuChild );
SetProp( hwndChild, PROP_ACCEL, 0 );
SetProp( hwndChild, PROP_MENUID, IDM_FIRSTWIN + iCount );
SetProp( hwndChild, PROP_ISMDI, TRUE );
/* Reflect change in WINDOW menu */
MdiAppendWindowToMenu( hwndChild );
/* Let's activate this MDI child */
hwndActive = GetProp( hwndMain, PROP_ACTIVE );
if ( GetProp( hwndMain, PROP_ZOOM ) )
{
MdiSwitchZoom( hwndChild, hwndActive );
}
MdiActivateChild( hwndChild, FALSE );
/* Show menu bar changes now */
DrawMenuBar( hwndMain );
}
return hwndChild;
}
/**/
/*
* MdiChildDefWindowProc( hwndChild, message, wParam, lParam ) : long;
*
* hwndChild Handle to document
* message Current message
* wParam Word parameter to message
* lParam Long parameter to message
*
* Handle MDI document messages. Messages reach here only after the
* application document window proedure has processed those that it
* wants. Major occurances that are recognized in this function
* include: child system menu choices, window creation, window
* activation, window destruction, and translating <alt>- into
* selecting the child system menu.
*
*/
long MdiChildDefWindowProc(
HWND hwndChild,
unsigned message,
WORD wParam,
LONG lParam )
{
HWND hwndMain; /* Handle to MDI desktop */
PAINTSTRUCT Paint; /* Paint structure */
hwndMain = GetParent( hwndChild );
switch ( message )
{
case WM_CLOSE:
/* We're going away */
MdiDestroyChildWindow( hwndChild );
break;
case WM_COMMAND:
switch( wParam )
{
case IDM_HIDE:
/* MDI child being hidden */
MdiHideChild( hwndChild );
break;
case IDM_RESTORE:
SendMessage( hwndChild, WM_SYSCOMMAND, SC_RESTORE, lParam );
break;
case IDM_MOVE:
SendMessage( hwndChild, WM_SYSCOMMAND, SC_MOVE, lParam );
break;
case IDM_SIZE:
SendMessage( hwndChild, WM_SYSCOMMAND, SC_SIZE, lParam );
break;
case IDM_MAXIMIZE:
SendMessage( hwndChild, WM_SYSCOMMAND, SC_MAXIMIZE, lParam );
break;
case IDM_PREVWINDOW:
/* This function is achieved only through the keyboard */
SendMessage( hwndChild, WM_SYSCOMMAND, SC_PREVWINDOW, lParam);
break;
case IDM_NEXTWINDOW:
/* This function is achieved only through the keyboard */
SendMessage( hwndChild, WM_SYSCOMMAND, SC_NEXTWINDOW, lParam);
break;
}
break;
case WM_INITMENU:
MdiInitSystemMenu( hwndChild );
break;
case WM_MENUCHAR:
/* Was the <alt>- key hit when no popup currently popped up? */
if ( ( LOWORD( lParam ) & MF_POPUP ) == 0 )
{
if ( wParam == '-' )
{
/* Let Alt-Minus mean activate our system menu */
return MAKELONG( 0, MC_SELECT );
}
else
{
/* Another <alt> key stroke, let the parent handle it */
SendMessage( hwndMain,
WM_SYSCOMMAND,
SC_KEYMENU,
( DWORD ) wParam );
return MAKELONG( 0, MC_ABORT );
}
}
break;
case WM_MENUSELECT:
iCurrentPopup = POP_CHILDSYS;
break;
case WM_MOUSEACTIVATE:
MdiActivateChild( hwndChild, FALSE );
break;
case WM_SYSCOMMAND:
switch( wParam & 0xFFF0 )
{
case SC_KEYMENU:
if ( GetProp( hwndMain, PROP_ZOOM ) || LOWORD(lParam) != '-' )
{
/* Pass any other Alt-Key messages to the parent */
return SendMessage(hwndMain,WM_SYSCOMMAND, wParam, lParam);
}
break;
case SC_MAXIMIZE:
if ( GetProp( hwndMain, PROP_ZOOM ) )
{
SetProp( hwndMain, PROP_ZOOM, FALSE );
MdiRestoreChild( hwndChild, TRUE );
}
else
{
SetProp( hwndMain, PROP_ZOOM, TRUE );
MdiZoomChild( hwndChild );
}
return 0L;
case SC_RESTORE:
if ( GetProp( hwndMain, PROP_ZOOM ) )
{
SetProp( hwndMain, PROP_ZOOM, FALSE );
MdiRestoreChild( hwndChild, TRUE );
}
return 0L;
case SC_NEXTWINDOW:
/* This function is achieved only through the keyboard */
MdiActivateNextChild( hwndChild );
return 0L;
case SC_PREVWINDOW:
/* This function is achieved only through the keyboard */
MdiActivatePrevChild( hwndChild );
return 0L;
}
break;
}
return DefWindowProc( hwndChild, message, wParam, lParam );
}
/**/
/*
* MdiGetMessage( hwndMain, lpMsg, hWnd, wMin, wMax ) : BOOL;
*
* hwndMain Handle to MDI desktop
* lpMsg Message structure to receive message
* hWnd Are messages for a specific window only?
* wMin Is there a minimum message number?
* wMax Is there a maximum message number?
*
* Get a normal windows message only after checking for keyboard
* access to the menus.
*
*/
BOOL MdiGetMessage(
HWND hwndMain,
LPMSG lpMsg,
HWND hWnd,
WORD wMin,
WORD wMax )
{
/* Process keyboard interface to menu */
MdiMenuMessageLoopUpdate( hwndMain );
/* Now go get the next message */
return GetMessage( lpMsg, hWnd, wMin, wMax );
}
/**/
/*
* MdiTranslateAccelerators( hwndMain, lpMsg ) : int
*
* hwndMain Handle to MDI desktop
* lpMsg Message structure containing message
*
* Translate this message via one of two accelerator tables:
* 1) The document's system menu (i.e. <ctrl><F4>)
* 2) The document's own accelerator table. This table
* is set with the MdiSetAccelerator() call.
*
*/
int MdiTranslateAccelerators(
HWND hwndMain,
LPMSG lpMsg )
{
int iResult = 0; /* Result of last translation */
HANDLE hAccel; /* Each of the two accel tables */
HWND hwndChild; /* Handle to document */
/* Is there a document on the MDI desktop? */
hwndChild = GetProp( hwndMain, PROP_ACTIVE );
if ( hwndChild )
{
/* Check for system accelerators */
hAccel = GetProp( hwndMain, PROP_CTRLACCEL );
iResult = TranslateAccelerator( hwndMain, hAccel, lpMsg );
if ( !iResult )
{
/* Check for document accelerators */
hAccel = GetProp( hwndChild, PROP_ACCEL );
if ( hAccel )
{
iResult = TranslateAccelerator( hwndMain, hAccel, lpMsg );
}
}
}
return iResult;
}